package com.yanfan.energybilling.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.yanfan.common.core.domain.AjaxResult;
import com.yanfan.common.utils.DictUtils;
import com.yanfan.common.utils.SecurityUtils;
import com.yanfan.community.building.domain.BuildingTreeSelect;
import com.yanfan.community.building.domain.CommunityBuilding;
import com.yanfan.community.building.service.ICommunityBuildingService;
import com.yanfan.energybilling.domain.vo.*;
import com.yanfan.energybilling.service.IEnergyStatisticsService;
import com.yanfan.energybilling.service.ITDEnergyDeductionRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.net.URLEncoder;

@Service
public class EnergyStatisticsServiceImpl implements IEnergyStatisticsService {

    @Autowired
    private ITDEnergyDeductionRecordService itdEnergyDeductionRecordService;
    @Autowired
    private ICommunityBuildingService commBuildingService;

    @Override
    public List<EnergyStatisticsVo> buildingEnergyStatistics() {
        List<EnergyStatisticsVo> list = itdEnergyDeductionRecordService.buildingEnergyStatistics();
        return Collections.emptyList();
    }

    @Override
    public List<EnergyCostStatisticsVo> energyCostStatisticsTimeWindow(StaticRequestParamVo param) {

        return itdEnergyDeductionRecordService.energyCostStatisticsTimeWindow(param);
    }

    @Override
    public List<EnergyCostStatisticsVo> energyConsumeStatisticsTimeWindow(StaticRequestParamVo param) {

        return itdEnergyDeductionRecordService.energyConsumeStatisticsTimeWindow(param);
    }

    @Override
    public BigDecimal energyCost(StaticRequestParamVo param) {
        return itdEnergyDeductionRecordService.energyCost(param);
    }

    @Override
    public Map<String, List<EnergyCostStatisticsVo>> energyCostStatisticsTimeWindows(StaticRequestParamVo param) {
        List<String> energyTypeList = param.getEnergyTypeList();
        if (CollectionUtil.isEmpty(energyTypeList)) return Collections.emptyMap();
        Map<String, List<EnergyCostStatisticsVo>> map = new HashMap<>();
        for (String s : energyTypeList) {
            String energyType = DictUtils.getDictLabel("energy_type", s, null);
            param.setEnergyType(s);
            List<EnergyCostStatisticsVo> energyCostStatisticsVos = itdEnergyDeductionRecordService.energyCostStatisticsTimeWindow(param);
            map.put(energyType, energyCostStatisticsVos);
        }
        return map;
    }

    @Override
    public Map<String, List<EnergyCostStatisticsVo>> energyCostStatisticsTimeWindowsByType(StaticRequestParamVo param) {
        List<String> typeList = param.getTypeList();
        if (CollectionUtil.isEmpty(typeList)) return Collections.emptyMap();
        Map<String, List<EnergyCostStatisticsVo>> map = new HashMap<>();
        //能源单价类
        for (String s : typeList) {
            String energyType = DictUtils.getDictLabel("price_scheme_type", s, null);
            param.setType(s);
            List<EnergyCostStatisticsVo> energyCostStatisticsVos = itdEnergyDeductionRecordService.energyCostStatisticsTimeWindow(param);
            map.put(energyType, energyCostStatisticsVos);
        }
        return map;
    }

    public Map<String, List<EnergyCostStatisticsVo>> energyCostStatisticsTimeWindowsByWater(StaticRequestParamVo param) {
        List<String> typeList = param.getEnergyTypeList();
        if (CollectionUtil.isEmpty(typeList)) return Collections.emptyMap();
        Map<String, List<EnergyCostStatisticsVo>> map = new HashMap<>();
        //能源单价类
        for (String s : typeList) {
            String energyType = DictUtils.getDictLabel("energy_type", s, null);
            param.setEnergyType(s);
            List<EnergyCostStatisticsVo> energyCostStatisticsVos = itdEnergyDeductionRecordService.energyCostStatisticsTimeWindowWater(param);
            map.put(energyType, energyCostStatisticsVos);
        }
        return map;
    }

    @Override
    public List<EnergyCostStatisticsVo> energyCostStatisticsTimeWindowsByDate(StaticRequestParamVo param) {
        return itdEnergyDeductionRecordService.energyCostStatisticsTimeWindowsByDate(param);
    }

    @Override
    public Map<String, List<EnergyCostStatisticsVo>> energyCostStatisticsTimeWindowsByBuilding(StaticRequestParamVo param) {
        Map<String, List<EnergyCostStatisticsVo>> map = new HashMap<>();
        List<CommunityBuilding> communityBuildings = new ArrayList<>();
        if (Objects.isNull(param.getBuildingId())) {
            communityBuildings = commBuildingService.selectSysBuildingList(null);
        } else {
            communityBuildings = commBuildingService.selectSysBuildingListByParentId(param.getBuildingId());
        }
        List<Long> buildingIdList = communityBuildings.stream().map(CommunityBuilding::getBuildingId).collect(Collectors.toList());

        for (Long id : buildingIdList) {
            param.setBuildingId(id);
            List<EnergyCostStatisticsVo> energyCostStatisticsVos = itdEnergyDeductionRecordService.energyCostStatisticsTimeWindow(param);

            // 使用Stream API查找id为10的对象
            Optional<CommunityBuilding> result = communityBuildings.stream()
                    .filter(item -> Objects.equals(item.getBuildingId(), id))
                    .findFirst();

            String name = "";
            // 检查是否找到了匹配的对象
            if (result.isPresent()) {
                CommunityBuilding obj = result.get();
                name = obj.getBuildingName();
            }

            map.put(name, energyCostStatisticsVos);
        }
        return map;
    }

    @Override
    public List<BuildingTreeSelect> buildingEnergyFlowStatistics(StaticRequestParamVo param) {
        CommunityBuilding communityBuilding = new CommunityBuilding();
        communityBuilding.setBuildingId(param.getBuildingId());
        List<BuildingTreeSelect> buildingTreeSelects = commBuildingService.buildingTree(communityBuilding);
        this.traverseAndSetValue(buildingTreeSelects, param);
        return buildingTreeSelects;
    }

    @Override
    public List<EnergyCostStatisticsVo> energyCountAllStatisticsTimeWindow(StaticRequestParamVo param) {
        return itdEnergyDeductionRecordService.energyCountAllStatisticsTimeWindow(param);
    }

    @Override
    public List<EquipmentEnergyBaseResp> energyComparisonOfTheSameCycle(StaticRequestParamVo param) {
        ArrayList<EquipmentEnergyBaseResp> res = new ArrayList<>();

        String deviceName = param.getDeviceName();
        param.setDeviceName(null);
        if (param.getCompareType() == 0) {
            param.setDateType("month");
            // 或者更精确的方式
            LocalDateTime startOfYear = LocalDate.now().with(TemporalAdjusters.firstDayOfYear()).atStartOfDay();
            LocalDateTime endOfYear = LocalDate.now().with(TemporalAdjusters.lastDayOfYear()).atTime(LocalTime.MAX);

            // 去年的开始时间 (1月1日 00:00:00)
            LocalDateTime startOfLastYear = LocalDate.now().minusYears(1).with(TemporalAdjusters.firstDayOfYear()).atStartOfDay();
            // 去年的结束时间 (12月31日 23:59:59)
            LocalDateTime endOfLastYear = LocalDate.now().minusYears(1).with(TemporalAdjusters.lastDayOfYear()).atTime(LocalTime.MAX);

            // 转换为 Date 类型
            Date startOfLastYearDate = Date.from(startOfLastYear.atZone(ZoneId.systemDefault()).toInstant());
            Date endOfLastYearDate = Date.from(endOfLastYear.atZone(ZoneId.systemDefault()).toInstant());
            param.setBegin(startOfLastYearDate);
            param.setEnd(endOfLastYearDate);
            List<EnergyCostStatisticsVo> lastYearStatisticsVos = itdEnergyDeductionRecordService.energyConsumeStatisticsTimeWindow(param);

            EquipmentEnergyBaseResp lastYearResp = new EquipmentEnergyBaseResp();
            lastYearResp.setEnergyDateList(lastYearStatisticsVos);
            res.add(lastYearResp);

            Date startOfThisYearDate = Date.from(startOfYear.atZone(ZoneId.systemDefault()).toInstant());
            Date endOfThisYearDate = Date.from(endOfYear.atZone(ZoneId.systemDefault()).toInstant());
            param.setBegin(startOfThisYearDate);
            param.setEnd(endOfThisYearDate);
            List<EnergyCostStatisticsVo> thisYearStatisticsVos = itdEnergyDeductionRecordService.energyConsumeStatisticsTimeWindow(param);

            EquipmentEnergyBaseResp thisYearResp = new EquipmentEnergyBaseResp();
            thisYearResp.setEnergyDateList(thisYearStatisticsVos);
            res.add(thisYearResp);


        } else {
            param.setDateType("day");
            // 或者更简洁的方式
            LocalDateTime startOfThisMonth = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay();
            LocalDateTime endOfThisMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).atTime(LocalTime.MAX);

            // 获取上月的开始时间 1号 00:00:00
            LocalDateTime startOfLastMonth = LocalDate.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay();
            // 获取上月的结束时间 最后一天 23:59:59
            LocalDateTime endOfLastMonth = LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).atTime(LocalTime.MAX);

            // 转换为 Date 类型
            Date startOfLastMonthDate = Date.from(startOfLastMonth.atZone(ZoneId.systemDefault()).toInstant());
            Date endOfLastMonthDate = Date.from(endOfLastMonth.atZone(ZoneId.systemDefault()).toInstant());
            param.setBegin(startOfLastMonthDate);
            param.setEnd(endOfLastMonthDate);
            List<EnergyCostStatisticsVo> lastYearStatisticsVos = itdEnergyDeductionRecordService.energyConsumeStatisticsTimeWindow(param);
            EquipmentEnergyBaseResp lastYearResp = new EquipmentEnergyBaseResp();
            lastYearResp.setEnergyDateList(lastYearStatisticsVos);
            res.add(lastYearResp);

            Date startOfThisMonthDate = Date.from(startOfThisMonth.atZone(ZoneId.systemDefault()).toInstant());
            Date endOfThisMonthDate = Date.from(endOfThisMonth.atZone(ZoneId.systemDefault()).toInstant());
            param.setBegin(startOfThisMonthDate);
            param.setEnd(endOfThisMonthDate);
            List<EnergyCostStatisticsVo> thisYearStatisticsVos = itdEnergyDeductionRecordService.energyConsumeStatisticsTimeWindow(param);

            EquipmentEnergyBaseResp thisYearResp = new EquipmentEnergyBaseResp();
            thisYearResp.setEnergyDateList(thisYearStatisticsVos);
            res.add(thisYearResp);

        }
        for (EquipmentEnergyBaseResp re : res) {
            re.setDeviceId(param.getDeviceId());
            re.setDeviceName(deviceName);
        }
        return res;
    }

    @Override
    public void exportEnergyDeviceHistory(HttpServletResponse response, StaticRequestParamVo param) {
        //数据
        List<EnergyCostStatisticsVo> energyCostStatisticsVos = energyCountAllStatisticsTimeWindow(param);
        //1.固定下载标头名称
        List<List<String>> head = new ArrayList<>();
        head.add(Collections.singletonList("设备名称"));
        head.add(Collections.singletonList("设备编号"));
        head.add(Collections.singletonList("能源类型"));
        head.add(Collections.singletonList("点位标识"));
        head.add(Collections.singletonList("总费用"));
        head.add(Collections.singletonList("总用量"));
        head.add(Collections.singletonList("时间"));
        // 2. 构造数据行（按写死顺序：设备名称等）
        List<List<Object>> data = new ArrayList<>();
        for (EnergyCostStatisticsVo vo : energyCostStatisticsVos) {
            List<Object> row = new ArrayList<>();
            row.add(vo.getDeviceName());
            row.add(vo.getSerialNumber());
            row.add(vo.getEnergyTypeStr());
            row.add(vo.getIdentity());
            row.add(vo.getTotalAmount());
            row.add(vo.getTotalValue());
            row.add(vo.getTime());
            data.add(row);
        }
        try{
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".csv");
            EasyExcel.write(response.getOutputStream())
                    .head(head)
                    .excelType(ExcelTypeEnum.CSV)
                    .sheet("历史数据")
                    .doWrite(data);
        }catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 递归遍历树节点并设置值
     */
    private void traverseAndSetValue(List<BuildingTreeSelect> treeNodes, StaticRequestParamVo param) {
        if (CollectionUtil.isEmpty(treeNodes)) {
            return;
        }

        for (BuildingTreeSelect node : treeNodes) {
            param.setBuildingId(node.getId());
            // 设置当前节点的值
//            itdEnergyDeductionRecordService.energyCost(param);
            BigDecimal energyCost = itdEnergyDeductionRecordService.energyCost(param);
            node.setValue(String.valueOf(energyCost.setScale(4, RoundingMode.HALF_UP)));

            // 递归处理子节点
            if (CollectionUtil.isNotEmpty(node.getChildren())) {
                traverseAndSetValue(node.getChildren(), param);
            }
        }
    }
}
